package com.ruoyi.quartz.task;

import com.github.tusharepro.core.TushareProService;
import com.github.tusharepro.core.bean.Daily;
import com.github.tusharepro.core.entity.DailyEntity;
import com.github.tusharepro.core.http.Request;
import com.ruoyi.quartz.util.TushareUtil;
import com.ruoyi.stock.domain.StockBasic;
import com.ruoyi.stock.domain.StockDaily;
import com.ruoyi.stock.service.IStockBasicService;
import com.ruoyi.stock.service.IStockDailyService;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.map.HashedMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Component;

/** 股票日线行情同步任务 */
@Component("stockDailyTask")
@Slf4j
public class StockDailyTask {

  @Autowired private IStockDailyService stockDailyService;

  @Autowired private IStockBasicService iStockBasicService;

  @Autowired private MongoTemplate mongoTemplate;

  private static final String COLLECTION_NAME = "stockDaily";

  private DateTimeFormatter yyyyMMdd = DateTimeFormatter.ofPattern("yyyyMMdd");

  public void run() {
    List<StockBasic> basicList = iStockBasicService.selectStockBasicList(new StockBasic());
    basicList.forEach(
        stockBasic -> {
          try {
            log.info("save stock daily :{}", stockBasic.getTsCode());
            int count =
                stockDailyService.count(
                    StockDaily.builder().tsCode(stockBasic.getTsCode()).build());
            if (count == 0) {
              List<DailyEntity> dailyList = stockDaily(stockBasic.getTsCode());
              Map<String, StockBasic> stockBasicMap = new HashedMap<>();
              stockBasicMap.put(stockBasic.getTsCode(), stockBasic);
              saveStockDaily(stockBasicMap, dailyList);
              Thread.sleep(1000);
            }
          } catch (IOException | InterruptedException e) {
            log.error(e.getMessage(), e);
          }
        });
  }

  public void run(String date) throws IOException {
    List<StockDaily> stockDailies =
        stockDailyService.selectStockDailyList(StockDaily.builder().tradeDate(date).build());
    if (CollectionUtils.isNotEmpty(stockDailies) && stockDailies.size() < 10000) {
      stockDailyService.deleteStockDailyByIds(
          stockDailies.stream().map(StockDaily::getId).collect(Collectors.toList()));
    }
    List<DailyEntity> dailyList = stockDailyToday(date);
    List<StockBasic> basicList = iStockBasicService.selectStockBasicList(new StockBasic());
    Map<String, StockBasic> stockBasicMap = new HashedMap<>();
    basicList.forEach(
        model -> {
          stockBasicMap.put(model.getTsCode(), model);
        });
    saveStockDaily(stockBasicMap, dailyList);
  }

  public void runToday() throws IOException {
    run(yyyyMMdd.format(LocalDate.now()));
  }

  private void saveStockDaily(Map<String, StockBasic> stockBasicMap, List<DailyEntity> dailyList) {
    if (!CollectionUtils.isEmpty(dailyList)) {
      List<StockDaily> collect =
          dailyList.stream()
              .parallel()
              .map(
                  daily -> {
                    StockBasic stockBasic = stockBasicMap.get(daily.getTsCode());
                    if (stockBasic == null) {
                      return null;
                    }
                    return StockDaily.builder()
                        .tsCode(daily.getTsCode())
                        .symbol(stockBasic.getSymbol())
                        .name(stockBasic.getName())
                        .market(stockBasic.getMarket())
                        .tradeDate(
                            daily.getTradeDate() == null
                                ? null
                                : yyyyMMdd.format(daily.getTradeDate()))
                        .open(BigDecimal.valueOf(daily.getOpen()))
                        .high(BigDecimal.valueOf(daily.getHigh()))
                        .low(BigDecimal.valueOf(daily.getLow()))
                        .close(BigDecimal.valueOf(daily.getClose()))
                        .preClose(BigDecimal.valueOf(daily.getPreClose()))
                        .change(BigDecimal.valueOf(daily.getChange()))
                        .pctChg(BigDecimal.valueOf(daily.getPctChg()))
                        .vol(BigDecimal.valueOf(daily.getVol()))
                        .amount(BigDecimal.valueOf(daily.getAmount()))
                        .build();
                  })
              .collect(Collectors.toList());
      stockDailyService.insertBatch(collect);
      //                        mongoTemplate.insertAll(collect);
    }
  }

  /** 股票日线行情接口 */
  private static List<DailyEntity> stockDaily(String tsCode) throws IOException {
    return TushareProService.daily(
        new Request<DailyEntity>(TushareUtil.getBuilder().copy().build()) {}.allFields()
            .param(Daily.Params.ts_code.value(tsCode)));
  }

  private static List<DailyEntity> stockDailyToday(String tradeDate) throws IOException {
    return TushareProService.daily(
        new Request<DailyEntity>(TushareUtil.getBuilder().copy().build()) {}.allFields()
            .param(Daily.Params.trade_date.value(tradeDate)));
  }
}
